package com.xuecheng.search.domain.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.search.domain.model.CourseSearchDo;
import com.xuecheng.search.domain.model.dto.EsPageResult;
import com.xuecheng.search.domain.model.po.CourseIndex;
import com.xuecheng.search.domain.service.CourseSearchService;
import com.xuecheng.search.infrastructure.util.EsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: LiJunXi
 * @Description:
 * @Date: 2024-09-01  10:16
 */
@Slf4j
@Service
public class CourseCourseSearchServiceImpl implements CourseSearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public EsPageResult<CourseIndex> list(CourseSearchDo courseSearchDo, String courseIndex) {
        SearchRequest searchRequest = new SearchRequest(courseIndex);
        // 设置参数
        SearchSourceBuilder searchSourceBuilder = setRequestParams(courseSearchDo);
        // 高亮设置
        HighlightBuilder highlightBuilder = EsUtil.setHighlight("name");
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (Exception e){
            log.error("es搜索出错，{}", e.getMessage());
            throw new XueChengPlusException("es搜索出错");
        }
        // 处理结果
        SearchHits hits = searchResponse.getHits();
        // 总数
        TotalHits totalHits = hits.getTotalHits();
        // 结果
        List<CourseIndex> resList = new ArrayList<>();
        for (SearchHit hit : hits.getHits()) {
            String sourceAsString = hit.getSourceAsString();
            CourseIndex courseIndexItem = JSONUtil.toBean(sourceAsString, CourseIndex.class);

            Long id = courseIndexItem.getId();
            String name = courseIndexItem.getName();
            // 取出高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (Objects.nonNull(highlightFields)){
                HighlightField highlightField = highlightFields.get("name");
                if (Objects.nonNull(highlightField)){
                    Text[] fragments = highlightField.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for (Text fragment : fragments) {
                        stringBuffer.append(fragment.string());
                    }
                    name = stringBuffer.toString();
                }
            }

            courseIndexItem.setId(id);
            courseIndexItem.setName(name);
            resList.add(courseIndexItem);
        }

        return new EsPageResult<>(resList, totalHits.value, courseSearchDo.getPageNo(), courseSearchDo.getPageSize(),
                EsUtil.getAggregation(searchResponse.getAggregations(), "mtAgg"),
                EsUtil.getAggregation(searchResponse.getAggregations(), "stAgg"));
    }

    /**
     * 设置搜索参数
     * @param courseSearchDo
     * @return
     */
    private SearchSourceBuilder setRequestParams(CourseSearchDo courseSearchDo) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        searchSourceBuilder =  EsUtil.setPages(searchSourceBuilder, courseSearchDo.getPageNo(), courseSearchDo.getPageSize());

        // 关键字
        if (StrUtil.isNotEmpty(courseSearchDo.getKeywords())){
            // 匹配关键字
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(courseSearchDo.getKeywords(),
                    "name", "desc");
            // 设置匹配占比
            multiMatchQueryBuilder.minimumShouldMatch("70%");
            // 提升另个字段的Boost值
            multiMatchQueryBuilder.field("name", 10);
            boolQueryBuilder.must(multiMatchQueryBuilder);
        }

        // 过滤
        if (StrUtil.isNotEmpty(courseSearchDo.getMt())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("mtName", courseSearchDo.getMt()));
        }
        if (StrUtil.isNotEmpty(courseSearchDo.getSt())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("stName", courseSearchDo.getSt()));
        }
        if (StrUtil.isNotEmpty(courseSearchDo.getGrade())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("grade", courseSearchDo.getGrade()));
        }

        // 布尔查询
        searchSourceBuilder.query(boolQueryBuilder);

        return searchSourceBuilder;
    }



}
